home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Software Vault: The Gold Collection
/
Software Vault - The Gold Collection (American Databankers) (1993).ISO
/
cdr47
/
asmwin13.zip
/
DEMO.ASM
next >
Wrap
Assembly Source File
|
1989-01-27
|
23KB
|
681 lines
TITLE 'Video Demo Program'
;
; This is a short program to demonstrate the VIDEO.ASM TASM Assembler module.
; You may use VIDDEMO.MAK to automate the assembly of this program. It is
; only designed to work in a 80x25 mode. (Video Modes 2, 3, & 7)
;
; All lines that make use of VIDEO.ASM routines or VIDEO.INC equates have
; been marked with ($) so you can scan through this file and see how to
; use the routine fairly easily.
;
; -- Dave
;
; ------------------------
; Jan 23, 1989
;
; I have revised this code some, to demo the windowing routines I have
; added, and to resize the DOS memory to the minimum required by the
; program. (This frees memory for the window routines).
;
; Tom Hill
IDEAL ; Use TASM's ideal mode
DOSSEG ; Use DOS segment ordering
MODEL SMALL ; Small memory model
INCLUDE 'VIDEO.INC' ; Global declarations for VIDEO.ASM
; ------
; Macros
; ------
MACRO Pause Seconds
LOCAL PauseLoop, KeyFound
;
; This macro will pause until a key is pressed.
;
; Uses:
; KeyPressed, ClearKBD
;
push ax ; Save regs
push cx
IFNB <Seconds>
mov cx, (Seconds*18)+(Seconds/5) ; 5 is recip of .2!
ELSE
mov cx, 91 ; 5 Seconds
ENDIF
PauseLoop:
call KeyPressed ; check for pressed key
or al, al ; Sets the zero flag if null
jnz KeyFound ; loop until key is pressed
call Delay ; Delay for .055 of a second
loop PauseLoop
KeyFound:
call ClearKBD ; Clear the key
pop cx ; Restore registers
pop ax
ENDM
; ---------------
; Program Equates
; ---------------
Version EQU '1.2'
Date EQU '01/23/89'
MaxRows EQU 25 ; Maximum rows
CenterRow EQU (MaxRows/2) ; Center row
MaxCols EQU 80 ; Maximum columns
CenterCol EQU (MaxCols/2) ; Center column
FillRows EQU 5 ; Number of rows for fill demo
FillCols EQU 20 ; Number of cols for fill demo
; -------------
; Stack Segment
; -------------
STACK 0FFFh
; -------------
; Data Segement
; -------------
; NOTE: Program relies on data being in current order. Do not reorder, delete
; or insert new data into the list. Data can be appended to this segment
; definition.
DATASEG
WTitle1 DB ' WINDOW #1 ',0
WTitle2 DB ' No frame ',0
WTitle3 DB ' #3 Window ',0
Title1 DB 'VIDEO.ASM - Direct Screen Writing Routines', 0
LABEL T1End BYTE
T1Len EQU (T1End-Title1-1)
Title2 DB 'Author: Dave Bennett / CompuServe 74635,1671',0
LABEL T2End BYTE
T2Len EQU (T2End-Title2-1)
Title2A DB 'Windowing routines added by Thomas Hill',0
LABEL T2AEnd BYTE
T2ALen EQU (T2AEnd-TItle2A-1)
Title3 DB 'Version ', Version, ' - Date: ', Date, 0
LABEL T3End BYTE
T3Len EQU (T3End-Title3-1)
Title4 DB 'Features:', 0
Title5 DB ' - Video mode detection', 0
Title6 DB ' - Monochrome/CGA/EGA support', 0
Title7 DB ' - Snow suppression', 0
Title8 DB ' - Direct character & string writing', 0
Title9 DB ' - Screen saving & restoring', 0
Title10 DB ' - Area fills (character, attribute, and both)', 0
Title11 DB ' - Cursor on & off control', 0
Title12 DB ' - All commands w/ or w/o attribute changes',0
Msg DB 'Direct Screen Writing is Fast!!!', 0
LABEL MsgEnd BYTE
MsgLen EQU (MsgEnd-Msg-1)
SaveMsg DB ' Screen has been saved... ', 0
LABEL SMsgEnd BYTE
SMsgLen EQU (SMsgEnd-SaveMsg-1)
CharMsg1 DB ' Character ', 0
CharMsg2 DB ' Writing!! ', 0
Wheel DB 179, '/-\', 179, '/-\' ; Wheel Chars
LABEL WheelEnd BYTE
MaxWheel EQU (WheelEnd-Wheel-1) ; Maximum Wheel offset
FillMsg1 DB '-AREA-', 0
FillMsg2 DB '-FILL-', 0
RestoreMsg DB ' Here''s your saved screen image! ', 0
LABEL RMsgEnd BYTE
RMsgLen EQU (RMsgEnd - RestoreMsg - 1)
VidModErr DB 'Invalid Video Mode!', 0Dh, 0Ah, '$'
MemError DB 'Cannot resize memory.',0Dh,0Ah,'$'
BadInit DB 'Error return from windows init.',0Dh,0Ah,'$'
RDir DB 0 ; Row Direction
CDir DB 0 ; Col Direction
; window handles
WHandle1 DB 0
WHandle2 DB 0
WHandle3 DB 0
; --------------------------
; Uninitialized Data Segment
; --------------------------
UDATASEG
LowTick DW (?) ; Tick holder for Delay routine
; ------------
; Code Segment
; ------------
CODESEG
mov ax, @data ; Set the
mov ds, ax ; Data segment
call ReSizeMem
call GetVideoMode ; Get vid mode data. MUST BE CALLED FIRST ($)
cmp [VideoMode], BW80 ; ($)
je VideoMode_OK ; Video Mode BW80 is ok
cmp [VideoMode], CO80 ; ($)
je VideoMode_OK ; Video Mode CO80 is ok
cmp [VideoMode], Mono ; ($)
je VideoMode_OK ; Monochrome is ok
mov dx, OFFSET VidModErr ; All other modes are unacceptable
mov ah, 09 ; DOS print string func
int 21h ; Call DOS
jmp ErrExit ; Exit the program
VideoMode_OK:
; mov [SnowCheck], 0 ; No Snow Checking! ($)
call CursorOff ; Turn the cursor off ($)
; --------------------
; Define some windows
; --------------------
call InitWindows
jnc Init_OK
mov dx,OFFSET BadInit
mov ah,09H
int 21H
jmp ErrExit
Init_OK:
mov ax,0A0AH ; Upper left corner 10,10
mov bx,0A0AH ; ten chars wide, ten rows deep
mov cx,0007H ; save underlay, frame it and clear it
mov dh,Reverse ; frame atrribute
mov dl,Normal ; background
mov si,OFFSET WTitle1 ; title one
call MakeWindow
mov [WHandle1],al ; save the handle
mov ax,0F28H ; 16,40
mov bx,0A20H ; 10 x 32
mov cx,0005H ; Save & fill, no frame
mov dh,Normal ; no frame, doesn't matter
mov dl,Reverse ; fill in reverse
mov si,OFFSET WTitle2 ; second title
call MakeWindow
mov [WHandle2],al
mov ax,0303H
mov bx,1440H ; 20 x 64
mov cx,0007H
mov dh,Normal
mov dl,Reverse
mov si,OFFSET WTitle3
call MakeWindow
mov [WHandle3],al
; ------------
; Title Screen
; ------------
call ClrScr ; Clear the screen
mov si, (OFFSET Title1) ; First Message
mov bh, Normal ; Gray on Black ($)
mov ah, 1 ; Start at top row
mov al, (CenterCol-(T1Len/2)) ; Center the message
call DWriteStr ; Write without attribute ($)
inc ah ; Double
inc ah ; Space
mov al, (CenterCol-(T2Len/2)) ; Center Title Msg 2
; NOTE: SI Already points to Title2 (See DATASEG)
call DWriteStr ; Write the string to the scr ($)
inc ah ; Single Space
mov al, (centerCol-(T2ALen/2))
call DWriteStr
inc ah
mov al, (CenterCol-(T3Len/2)) ; Center title Msg 3
call DWriteStr ; Write string to scr ($)
inc ah ; Double
inc ah ; Space
mov al, (CenterCol-(T1Len/2)) ; Align with first row
call DWriteStr ; Write str to scr ($)
inc ah ; Double
inc ah ; Space
inc al ; Indent
inc al ; 2 Spaces
mov cx, 8 ; 8 Feature lines
TS_Features:
call DWriteStr ; Write a feature ($)
inc ah ; Double
inc ah ; Space
loop TS_Features ; Loop for all feature lines
Pause <10> ; Wait for a pressed key (10 seconds)
;---------------
; DFillAttr Demo
; --------------
cmp [VideoMode], Mono ; This code is'nt suited for mono ($)
je DWN_Begin ; So goto DWriteStNA demo if mono
mov ax, 0101h ; First row/First column
mov bh, MaxRows ; All rows
mov bl, MaxCols ; All columns
mov dh, 1 ; Initialize attribute
DFA_Top:
and dh, 00001111b ; Clear all but foreground
cmp dh, 0 ; Check for no attribute
jne DFA_Fill ; Go ahead if attribute
inc dh ; Make sure theres and attr
DFA_Fill:
call DFillAttr ; Fill screen with attribute ($)
call Delay ; Delay for .055 of a second
inc dh ; Next Attribture
push ax ; Store row/col info
call KeyPressed ; Check for a key
or al, al ; Sets zero flag if no char
pop ax ; Restore row/col info
jz DFA_Top ; If no key the loop
call ClearKBD ; Clear key(s) from buffer
;-----------------
; DWriteStrNA Demo
; ----------------
DWN_Begin:
call ClrScr ; Clear the screen
mov ax, 0 ; Initialize row/col
mov bh, Normal ; Initialize Attribute ($)
DWN_MoveMsg:
mov si, OFFSET Msg ; Point to Msg
test [RDir], 1 ; Check the direction
jz DWN_RInc ; If direction is right then goto RInc
dec ah ; Decrement the row
cmp ah, 1 ; Check to see if row eq 1
jne DWN_CheckCol ; If not then check columns
inc [RDir] ; Change the direction
jmp DWN_CheckCol ; Check columns
DWN_RInc:
inc ah ; Increment the row
cmp ah, MaxRows ; Check to see if row eq MaxRows
jne DWN_CheckCol ; If not then check columns
inc [RDir] ; Change the row-wise direction
DWN_CheckCol:
test [CDir], 1 ; Check column wise direction
jz DWN_CInc ; If direction is down then goto CInt
dec al ; Decrement the row (Go up)
cmp al, 1 ; Check to see if this is column one
jne DWN_WriteIt ; If not then check attr
inc [CDir] ; Change the direction
jmp DWN_WriteIt ; Check the attr
DWN_CInc:
inc al ; Increment the row
cmp al, (MaxCols-MsgLen) ; Check to see if row eq MaxCols
jne DWN_WriteIt ; If not then check attr
inc [CDir] ; Change the column-wise direction
DWN_WriteIt:
call DWriteStrNA ; Write the str on scr w/o attr change ($)
push ax ; Store ax reg
call KeyPressed ; Check to see if a key has been pressed
or al, al ; Does AL eq zero?
pop ax ; Restore registers
jz DWN_MoveMsg ; if Yes then Redisplay message
call ClearKBD ; Clear the keyboard
; --------------
; DWriteStr Demo
; --------------
cmp [VideoMode], Mono ; Demo not well suited for mono ($)
je Windows ; so goto window demo if mono
DW_MoveMsg:
mov si, OFFSET Msg ; Point to Msg
test [RDir], 1 ; Check the direction
jz DW_RInc ; If direction is right then goto RInc
dec ah ; Decrement the row
cmp ah, 1 ; Check to see if row eq 1
jne DW_CheckCol ; If not then check columns
inc [RDir] ; Change the direction
jmp DW_CheckCol ; Check columns
DW_RInc:
inc ah ; Increment the row
cmp ah, MaxRows ; Check to see if row eq MaxRows
jne DW_CheckCol ; If not then check columns
inc [RDir] ; Change the row-wise direction
DW_CheckCol:
test [CDir], 1 ; Check column wise direction
jz DW_CInc ; If direction is down then goto CInt
dec al ; Decrement the row (Go up)
cmp al, 1 ; Check to see if this is column one
jne DW_CheckAttr ; If not then check attr
inc [CDir] ; Change the direction
jmp DW_CheckAttr ; Check the attr
DW_CInc:
inc al ; Increment the row
cmp al, (MaxCols - MsgLen) ; Check to see if row eq MaxCols
jne DW_CheckAttr ; If not then check attr
inc [CDir] ; Change the column-wise direction
DW_CheckAttr:
inc bh ; Increment the attribute
test bh, Blink ; Test to see if blink bit is on
jz DW_WriteIt ; If not then skip to WriteIt
mov bh, 1 ; Set BH eq 1
DW_WriteIt:
call DWriteStr ; Write the string on the screen ($)
push ax ; Store ax reg
call KeyPressed ; Check to see if a key has been pressed
or al, al ; Does AL eq zero?
pop ax ; Restore registers
jz DW_MoveMsg ; if Yes then Redisplay message
call ClearKBD ; Clear the keyboard
Pause <10> ; Macro to pause for 10 seconds
; --------------------
; Display some windows
; --------------------
Windows:
mov al,[WHandle1]
call DispWindow ; window 1
Pause
mov al,[WHandle2]
call DispWindow
Pause
mov al,[WHandle3]
call DispWindow
Pause
push si ; let's write some strings!
mov ax,080AH
mov bh,Normal
mov bl,8
WLoop:
mov si,OFFSET Title4
mov cx,8 ; 8 Feature lines
WLoop2:
call WWriteStr ; Write a feature ($)
loop WLoop2 ; Loop for all feature lines
dec bl
jnz WLoop ; fill up the window, and then some
pop si
Pause <10>
call EraseTopWin
Pause
call EraseTopWin
Pause
call EraseTopWin
Pause
; -------------
; DWriteCH Demo
; -------------
CharMsg1Col = 24
CharMsg2Col = 48
RowStart = 1 ; Row to start in
ColStart = 6 ; Column to start in
; Note: SI already points to CharMsg1 (See DATASEG)
call ClrScr ; Clear the screen
mov ah, CenterRow ; Middle row of screen
mov bh, (Brown*10h+Blue) ; Blue on Brown (Also ul mono) ($)
mov al, CharMsg1Col ; Point to column for first msg
call DWriteStr ; Write the first string ($)
; Note: SI now points to CharMsg2 (See DATASEG)
mov al, CharMsg2Col ; Column for second msg
call DWriteStr ; Write the second string ($)
mov ah, RowStart ; Start row
mov al, ColStart ; Start column
mov bh, White ; White on black ($)
mov cx, 1 ; One Character
mov si, OFFSET Wheel ; Offset of wheel characters
DWC_Top:
mov bl, [Byte Ptr si] ; Load character into bl
DWC_WriteIt:
call DWriteCH ; Write the character ($)
inc ah ; Next row
inc al ; Next column
cmp ah, MaxRows ; Check AH against Maximum rows
jle DWC_CheckCol ; If less then then Check columns
mov ah, 1 ; Reset row
DWC_CheckCol:
cmp al, MaxCols ; Check AL agains max cols
jle DWC_WriteIt ; If less than max cols then write
mov ah, RowStart ; Reset row
mov al, ColStart ; Reset col
; call Delay ; Wait 1 / 18.2 of a second
inc si ; Point to next character in wheel
cmp si, (OFFSET Wheel + MaxWheel) ; Maximum offset of Wheel
jle DWC_Top
DWC_InKey:
push ax ; Store row/col info
call KeyPressed ; Check to see if a key has been pressed
or al, al ; Sets zero flag if al eq 0
pop ax ; Restore row/col info
jnz DWC_End ; If a key has been press (not null) then end
mov si, OFFSET Wheel ; Set SI to offset zero of wheel
jmp DWC_Top ; If zero flag set then loop
DWC_End:
call ClearKBD ; Clear the keyboard
; ------------
; DFillCH Demo
; ------------
FillMsgCol = 36 ; Fill Msgs in column 25
FillMsg1Row = 3 ; Message one in row 3
FillMsg2Row = 20 ; Message two in row 20
FillWid = 15 ; Width of fill
FillHt = 4 ; Fill Height
RInc = 2 ; Row Increment
CInc = 7 ; Column Increment
call ClrScr ; Clear the screen
mov ah, FillMsg1Row ; Row for first msg
mov al, FillMsgCol ; Col for the msg
mov bh, LightBlue+Blink ; LightBlue on Black w/ Blink (ul mono) ($)
; NOTE: SI Points to first msg already
call DWriteStr ; Write the first message (SI points to 2nd) ($)
mov ah, FillMsg2Row ; Row for the second message
call DWriteStr ; Write the second message to the screen ($)
mov ax, 0101h ; Top row / Left Col
mov bh, FillHt ; Number of rows
mov bl, FillWid ; Number of columns
mov dh, 00h ; Initialize attr
DFCH_Top:
inc dh ; Increment dh
mov dl, dh ; Move attribute to character
call DFillCh ; Do the fill ($)
add ah, RInc ; Increment rows
add al, CInc ; Increment columns
cmp ah, (MaxRows-FillHt) ; compare ah to max rows - fill ht
jle DFCH_CheckCol ; If less than or equal to then check columns
jmp DFCH_SecPart ; Goto the second part
DFCH_CheckCol:
cmp al, (MaxCols-FillWid) ; compare al to max cols - fill width
jle DFCH_Top ; Jump to the top if in bounds
DFCH_SecPart:
mov dh, 0 ; Initialize the attribute
mov ah, 1 ; Top Row
mov al, (MaxCols-FillWid) ; Right Side
DFCH_Top2:
inc dh ; Increment dh
mov dl, dh ; Move attribute to character
call DFillCh ; Do the fill
add ah, RInc ; Increment rows
sub al, CInc ; Decrement columns
cmp ah, (MaxRows-FillHt) ; compare ah to max rows - fill ht
jle DFCH_CheckCol2 ; If less than or equal to then check columns
jmp DFCH_Pause ; Goto the pause routine
DFCH_CheckCol2:
cmp al, 1 ; compare al to 1 (First column)
jg DFCH_Top2 ; Jump to the top if in bounds
DFCH_Pause:
Pause <10> ; Macro to pause 10 seconds
Exit:
call EraseTopWin ; recover first window (original screen)
ErrExit:
call CursorOn ; Turn the cursor on ($)
mov ah, 4Ch ; DOS exit function
int 21h ; Call DOS to exit
; -------------------
; Programs Procedures
; -------------------
PROC ReSizeMem
;
; This procedure will calulate the current size of the program,
; and return the unused memory to the DOS system.
;
push ax
push bx
push cx
push dx
mov ah,62H ; Get PSP Address (DOS 3 and above only)
int 21H
mov ax,SS ; stack segment
sub ax,bx ; segment difference
mov cx,4
shl ax,cl ; make value be bytes
mov bx,ax ; save it
mov ax,SP ; use top of stack as end of program marker
mov cx,10H ; plus some slack
add ax,cx
add ax,bx ; figure program size.
mov cx,4
shr ax,cl ; make into paragraphs
mov bx,ax
mov ah,4AH ; resize allocated memory
int 21H ; do it.
pop dx
pop cx
pop bx
pop ax
jnc ReSizeOK ; no problems
mov dx,OFFSET MemError
mov ah,09H
int 21H
jmp ErrExit
ReSizeOK:
ret
ENDP ResizeMem
PROC ClrScr
;
; This procedure Clears the screen using VIDEO.ASM
;
push ax ; Store registers
push bx
push dx
mov ax, 0101h ; First row & col
mov bh, MaxRows ; All Rows
mov bl, MaxCols ; All Columns
mov dh, Normal ; Attr = Gray on Black ($)
mov dl, ' ' ; Fill scr with spaces
call DFillCH ; Do it! ($)
pop dx ; Restore registers
pop bx
pop ax
ret
ENDP ClrScr
PROC KeyPressed
;
; This procedure uses DOS to check if a key has been pressed.
;
; Output
; AL = FFh/0 Yes/No
; Modifies
; AX
;
mov ah, 0Bh ; DOS func 0Bh (Check for pressed key)
int 21h ; Call DOS
xor ah, ah ; Clear AH reg
ret
ENDP KeyPressed
PROC ClearKBD
;
; This procedure uses DOS to clear the keyboard buffer.
;
push ax ; Store AX reg
mov ax, 0C00h ; Dos func 0Ch = Clear KBD
int 21h ; Call DOS
pop ax ; Restore AX
ret
ENDP ClearKBD
PROC Delay
;
; This procedure delays the CPU for about 1 timer tick or 1/18.2 of
; of a second.
;
push ax
push cx
push dx
mov ah,0 ; INT 1A GetTime function
int 01ah ; Call timer interrupt
mov [LowTick], dx ; DX returns low timer tick value
DelayLoop:
mov ah, 0 ; INT 1A GetTime function
int 01ah ; Call timer interrupt
cmp dx, [LowTick] ; Compare current val to first
je DelayLoop ; If still the same then loop
pop dx
pop cx
pop ax
ret
ENDP Delay
END ; Of VidDemo.ASM